import { vectorStore } from './vectorStore.js'
import { modelService } from './model.js'
import logger from './logger.js'

export class ChatService {
  constructor() {
    this.vectorStore = vectorStore
    this.collectionName = 'documents'
    this.maxHistoryLength = 5  // 保留最近5轮对话
    this.modelService = modelService
  }

  async generateResponse(message, history = []) {
    try {
      // 1. 生成问题的嵌入向量
      const questionEmbedding = await this.modelService.generateEmbedding(message)

      // 2. 在 Milvus 中搜索相关文档
      const searchResults = await this.searchRelevantDocuments(questionEmbedding)

      // 3. 构建提示词（包含历史对话）
      const prompt = this.buildPrompt(message, searchResults, history)

      // 4. 调用 Ollama 生成回答
      const response = await this.modelService.generateResponse(prompt)

      return {
        answer: response,
        sources: searchResults.data?.map(doc => ({
          title: doc.title,
          content: doc.content.substring(0, 200) + '...',
          score: doc.score
        }))
      }
    } catch (error) {
      logger.error('生成回答失败:', error)
      throw error
    }
  }

  async searchRelevantDocuments(embedding, limit = 3) {
    try {
      logger.debug('Searching relevant documents with params:', {
        embeddingLength: embedding?.length,
        limit
      })

      const searchResults = await this.vectorStore.search(embedding, {
        limit,
        minScore: 0.3,
        fields: ['id', 'title', 'content']
      })

      logger.info('Search results:', {
        count: searchResults.data?.length || 0,
        scores: searchResults.data?.map(doc => doc.score)
      })

      return searchResults
    } catch (error) {
      logger.error('Failed to search relevant documents:', {
        error: error.message,
        embeddingLength: embedding?.length
      })
      return { data: [], total: 0 }
    }
  }

  buildPrompt(message, relevantDocs = [], history = []) {
    // 如果没有相关文档，使用基础提示词
    if (!relevantDocs.data?.length) {
      return `你是一个友好的AI助手。请回答用户的问题：${message}`
    }

    // 确保 history 是数组
    const messageHistory = Array.isArray(history) ? history : []
    
    // 构建上下文
    let context = ''
    if (relevantDocs.data?.length > 0) {
      context = '参考以下文档：\n\n' + relevantDocs.data
        .map(doc => `${doc.content}`)
        .join('\n\n')
    }

    // 构建历史对话
    let conversationHistory = ''
    if (messageHistory.length > 0) {
      conversationHistory = messageHistory
        .slice(-this.maxHistoryLength)  // 只保留最近几轮对话
        .map(msg => `${msg.role === 'user' ? '用户' : 'AI助手'}: ${msg.content}`)
        .join('\n')
    }

    // 构建完整提示词
    let prompt = `你是一个专业的智能助手。请基于以下参考文档回答用户的问题。

要求：
1. 回答要简洁、准确，并且只使用参考文档中的信息
2. 如果参考文档中的信息不足以回答问题，请明确说明
3. 如果需要更多信息才能回答，请说明还需要什么信息
4. 回答要有逻辑性和连贯性
5. 如果问题涉及多个方面，请分点回答\n\n`

    if (context) {
      prompt += `${context}\n\n`
    }
    if (conversationHistory) {
      prompt += `历史对话：\n${conversationHistory}\n\n`
    }
    prompt += `用户: ${message}\nAI助手: `

    return prompt
  }

  async *generateResponseStream(question, history = []) {
    try {
      // 1. 生成问题的向量表示
      const questionEmbedding = await this.modelService.generateEmbedding(question)
      
      // 2. 搜索相关文档
      const searchResults = await this.vectorStore.search(questionEmbedding, { limit: 5 })
      
      // 3. 构建提示词
      const prompt = this.buildPrompt(question, searchResults, history)
      
      try {
        // 4. 如果有相关文档，先发送源文档信息
        if (searchResults.data?.length > 0) {
          yield {
            type: 'sources',
            data: searchResults.data.map(doc => ({
              id: doc.id,
              title: encodeURIComponent(doc.title),
              content: encodeURIComponent(doc.content),
              score: doc.score
            }))
          }
        }

        // 5. 使用流式生成回答
        logger.info('Generating response stream')
        for await (const chunk of this.modelService.generateResponseStream(prompt)) {
          yield {
            type: 'text',
            data: chunk
          }
        }
      } catch (error) {
        logger.error('Failed to generate response:', error)
        yield {
          type: 'text',
          data: '抱歉，我现在无法回答您的问题。请稍后再试。'
        }
      }
    } catch (error) {
      logger.error('Failed to generate response:', error)
      throw error
    }
  }
} 